#include "linkedlists.h"

/*
	[head]<------------------------------->[tail]
*/


List* List_New (void)
{
 List* list = NULL;

	list = malloc (sizeof (*list));
	if (list != NULL)
	{
		list->counter = 0;
		list->head = NULL;
		list->tail = NULL;
		list->iter = NULL;
	}

 return (list);
}

void* List_InitIter (List *myList)
{
	if (myList == NULL)
		return NULL;

	myList->iter = myList->head;
	if (myList->iter == NULL)
		return NULL;

	return (myList->iter->data);
}

void* List_IterNext (List *myList)
{
	if(!myList)
	{
		return NULL;
	}
	if (!myList->iter)
		return NULL;

	myList->iter = myList->iter->next;

	if (!myList->iter)
		return NULL;

	return (myList->iter->data);
}

int List_Count (List *myList)
{
	if (!myList)
		return -1;

	return (myList->counter);
}

int List_PushHead (List *myList, void* element)
{
  Data *new = NULL;

	new = malloc (sizeof (Data));
	if (new != NULL)
	{
		new->data = element;
		new->next = NULL;
		new->pred = NULL;

		if (myList->head == NULL)
		{
			myList->head = new;
			myList->tail = new;
		}
		else
		{
			new->next = myList->head;
			myList->head->pred = new;
			myList->head = new;
		}

		myList->counter ++;
	}
	else
	{
		return -1;
	}

 return 0;
}

int List_PushTail (List *myList, void* element)
{
  Data *new = NULL;

	new = malloc (sizeof (Data));
	if (new != NULL)
	{
		new->data = element;
		new->next = NULL;
		new->pred = NULL;

		if (myList->tail == NULL)
		{
			myList->head = new;
			myList->tail = new;
		}
		else
		{
			new->pred = myList->tail;
			myList->tail->next = new;
			myList->tail = new;
		}

		myList->counter ++;
	}
	else
	{
		return -1;
	}

 return 0;
}

void* List_PopHead (List *myList)
{
	void *element = NULL; 
	Data *data = NULL;

	if (myList->head != NULL)
	{
		data = myList->head;
		element = data->data;

		if (myList->head == myList->tail)
		{
			myList->head = NULL;
			myList->tail = NULL;
		}
		else
		{
			myList->head = myList->head->next;
			myList->head->pred = NULL;
		}

		myList->counter --;
		free (data);
	}	

 return (element);
}

void* List_PopTail (List *myList)
{
	void *element = NULL; 
	Data *data = NULL;

	if (myList->tail != NULL)
	{
		data = myList->tail;
		element = data->data;

		if (myList->head == myList->tail)
		{
			myList->head = NULL;
			myList->tail = NULL;
		}
		else
		{
			myList->tail = myList->tail->pred;
			myList->tail->next = NULL;
		}

		myList->counter --;
		free (data);
	}	

 return (element);
}

void* List_Pop (List *myList, Data** element)
{
	void* elm = NULL;

	if (myList != NULL)
	{
		if (myList->head != NULL)
		{
			if (myList->head == *element)
			{
				myList->head = myList->head->next;
			}
			if (myList->tail == *element)
			{
				myList->tail = myList->tail->pred;
			}
			if ((*element)->pred)
				(*element)->pred->next = (*element)->next;
			if ((*element)->next)
				(*element)->next->pred = (*element)->pred;

			myList->counter --;
			elm = (*element)->data;
			free (*element);
			*element = NULL;
		}
	}

 return (elm);
}

void List_Del (List *myList, Data** element)
{
	if (myList != NULL)
	{
		if (myList->head != NULL)
		{
			if (myList->head == *element)
			{
				myList->head = myList->head->next;
			}
			if (myList->tail == *element)
			{
				myList->tail = myList->tail->pred;
			}
			if ((*element)->pred)
				(*element)->pred->next = (*element)->next;
			if ((*element)->next)
				(*element)->next->pred = (*element)->pred;

			myList->counter --;
			/*free ((*element)->data);*/
			free (*element);
			*element = NULL;
		}
	}
}

void List_Destroy (List **myList)
{
 Data *data = NULL,
	  *temp = NULL;

/*
############ Replace by that##############
	while ((iter = List_PopHead (*myList)) != NULL)
	{
		clear element;
	}
	free mylist;
*/

	if (myList != NULL)
	{
		data = (*myList)->head;
		while(data != NULL){
			temp = data;
			data = data->next;
			free (data->data);
			List_Del (*myList, &temp);
		}
		free (*myList);
		*myList = NULL;
	}
}

